package com.annotation;

import com.annotation.bean.Person;
import com.annotation.configure.*;
import com.annotation.service.TestService;
import com.annotation.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.junit.Test;
public class MainTest {

    private static final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestConfig.class);


    @Test
    public void jdbcTestConfig() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestDataSourceConfig.class);
        UserService bean = context.getBean(UserService.class);

        //发布事件
        context.publishEvent(new ApplicationEvent(new String("自定义发布的事件")){

        });
        bean.insert();


    }



    @Test
    public void aspectJconfig() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestAspectJConfig.class);


        System.out.println(context);

    }

    /**
     *  21
     */
    @Test
    public void testAutowared() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestDataSourceConfig.class);
        TestService bean = context.getBean(TestService.class);
        System.out.println(bean);

    }

    /**
     * 测试属性赋值 @Value()
     *
     *  1.基本数值  @Value()
     *  2.可以写Spel表达式  #{}
     *  3.可以使用${}  可以从环境变量、配置文件【properties】中取值
     *
     *  20
     */
    @Test
    public void propertyValue() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestConfigOfPropertyValues.class);
        //printBean(context);
        Person  person= (Person) context.getBean("person");
        ConfigurableEnvironment environment = context.getEnvironment();
        String property = environment.getProperty("person.niceName");
        System.out.println(property);

    }


    /**
     * 测试bean的自定义初始化和销毁的生命周期
     */
    @Test
    public void testLifeCycle() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestConfigOfLifeCycle.class);
        printBean(context);
        Object car = context.getBean("dog");     //car   bike  dog

        //BeanUtils.remoreBean(context,"bike"); //  car bike   dog

        context.removeBeanDefinition("dog"); //bike  car dog
        // System.out.println(car);

    }


    /**
     * 总结  ：给IOC容器中注入Bean的方式有哪些
     * 1.使用 @Controller  @Service  @Component  @Repository   @Configuration  @ComponentScan  @ComponentScans加入注解方式【自己写的类】
     * 2.第三方包   使用@Bean[第三方包导入的组件]
     * 3.使用@Condition注解，@ConditionOnExpress()注解，满足该注解里面的Condition接口的判断条件，才能够注入，和@Bean注解一起用。
     * 3.使用@Import[快速导入一个组件]
     * 4.使用@ImportSelector:  返回需要导入的组件的全类名
     * 5.使用ImportBeanDefinitionRegistrar   手工加入Bean   自定义实现ImportBeanDefinitionRegistrar接口  然后直接将Bean加入到BeanDefinition中
     * 6.使用Spring提供FactoryBean(工厂Bean)  通过FactoryBean ，Spring容器在获取对象时候，获取的是该工厂Bean创建的对象，如果想用IOC容器获取FactoryBean，在获取的
     * 工厂Bean本身的时候，可以加上&符号
     */
    @Test
    public void test2() {
        ApplicationContext context = new AnnotationConfigApplicationContext(TestConfig2.class);
        Object person = context.getBean("person");
        Object person1 = context.getBean("person");
        System.out.println(person == person1);
        /**
         * 用于解除对FactoryBean实例的引用，并将其与FactoryBean创建的bean区分开来。例如，如果名为myJndiObject的bean是一个FactoryBean，
         * 那么获取&myJndiObject将返回工厂，而不是工厂返回的实例。
         */
        Object creatColorFunctoryBean = context.getBean("&colorFunctoryBean");
        System.out.println(creatColorFunctoryBean);
    }


    @Test
    public void testImport() {
        printBean(context);
    }


    /**
     * 测试Bean的包扫描方案
     */
    @Test
    public void test1() {
        ApplicationContext context = new AnnotationConfigApplicationContext(TestConfig.class);
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String bean : beanDefinitionNames) {
            System.out.println(bean);
        }

    }

    private void printBean(ApplicationContext context) {

        String[] beanDefinition = context.getBeanDefinitionNames();
        for (String bean : beanDefinition) {
            System.out.println(bean);
        }

    }


}
